# encoding: utf-8
import Template
import Config
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
import re, time
from pypinyin import lazy_pinyin, Style, pinyin

import QrCode
from PIL import Image
import base64
import io
import SendEmail as SendEmail

class Qiangpiao(object):
    def __init__(self):
        # 邮箱配置
        self.mail_host = "smtp.qq.com"  # 设置服务器
        self.search_time = 0
        self.life   = 0
        # 确定抢票车次
        self.sure_train = ''
        config = Config.Config()
        baseConfig = config.getBaseConfig(self)
        self = baseConfig
        self.driver = webdriver.Chrome()

        self.qrCodeClass = QrCode.QrCode(self.driver)
        self.emailClass = SendEmail.SendEmail(self.mail_host, self.mail_user, self.mail_pass, self.sender)

    # 输入个人信息及车次信息
    def _inputInfo(self):
        config = Config.Config()
        inputConfig = config.getInputConfig(self)
        self = inputConfig

    # 登录12306
    def _login(self):
        self._inputInfo()
        self.driver.get(self.login_url)
        # 使用账户密码
        if self.isAccountLogin == '1':
            if self._useUsernameLogin() == False:
                shortMessageClose = self.driver.find_element(By.ID, 'short_message_close')
                shortMessageClose.click()
                if self._useUsernameQrCode() == False:
                    return False
                self.driver.back()
        else:
            if self._useUsernameQrCode() == False:
                    return False
            self.driver.back()
        
        WebDriverWait(self.driver, 1000).until(
            EC.url_to_be(self.initMy_url)
        )

    #账户密码登陆 
    def _useUsernameLogin(self):
        username = self.driver.find_element(By.ID, 'J-userName')
        password = self.driver.find_element(By.ID, 'J-password')
        username.send_keys(self.username)
        password.send_keys(self.password)
        queryBtn = self.driver.find_element(By.ID, 'J-login')
        queryBtn.click()

        wait = WebDriverWait(self.driver, 10)
        wait.until(EC.presence_of_element_located((By.ID, 'modal')))
        wait.until(
            EC.presence_of_element_located((By.ID, 'id_card')),
        )
        idCard = self.driver.find_element(By.XPATH, '//*[@id="id_card"]')
        element = wait.until(EC.element_to_be_clickable((By.ID, "id_card")))
        element.send_keys(self.entity)
        idCard.click()
        verificationCode = self.driver.find_element(By.ID, 'verification_code')
        verificationCode.click()
        time.sleep(2)
        message = self.driver.find_element(By.XPATH, '//*[@id="message"]/p')
        if message.text != '获取手机验证码成功！':
            return False
        else:
            return True
        
    # 二维码登陆
    def _useUsernameQrCode(self):
        toolbarDiv = self.driver.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[2]/a')
        toolbarDiv.click()

        time.sleep(3)
        qrCodeElement = self.driver.find_element(By.XPATH, '//*[@id="J-qrImg"]')
        qrCodeUrl = qrCodeElement.get_attribute('src')
        # 下载二维码图片
        self.driver.get(qrCodeUrl)
        imageData = base64.b64decode(self.driver.current_url.split(',')[1])
        qrCodeImage = Image.open(io.BytesIO(imageData))
        # 保存二维码图片
        qrCodeImage.save('qr_code.png')
        return self.emailClass.sendEmailQrCode(self.my_mail)

    def get_pinyin(self, train):
        # 获取拼音首字母
        pinyin_initials = lazy_pinyin(train)

        # 将拼音首字母连接成字符串
        pinyin_initials_str = ",".join(pinyin_initials)

        # 输出结果
        return pinyin_initials_str
    # 检测车票信息输入
    def _search_infor(self):
        # 1.跳转到查票页面
        self.driver.get(self.search_url)
        wait = WebDriverWait(self.driver, 10)

        # 判断出发地是否能被点击
        element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="fromStationText"]')))
        startAddress = self.driver.find_element(By.XPATH, '//*[@id="fromStationText"]')
        startAddress.click()
        startAddressList = self.hotAddressFind(wait)
        isFind = 0
        for address in startAddressList:
            if address.text == self.start:
                address.click()
                isFind = 1
                break
        if isFind == 0:
            startAddress.click()
            words = ''
            start_py = self.get_pinyin(self.start)
            for word in start_py.split(','):
                words = words + word
            startAddress.send_keys(words)
        time.sleep(1)
        isFind = self.isHavePage(wait, isFind, self.start)
        if isFind == 0:
            print('出发地输入错误')
            return False
        
        # 判断目的地能否被点击
        element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="toStationText"]')))
        toStationAddress = self.driver.find_element(By.XPATH, '//*[@id="toStationText"]')
        toStationAddress.click()
        toStationAddressList = self.hotAddressFind(wait)
        isFind = 0
        for address in toStationAddressList:
            if address.text == self.to_station:
                address.click()
                isFind = 1
                break
        if isFind == 0:
            toStationAddress.click()
            words = ''
            to_station_py = self.get_pinyin(self.to_station)
            for word in to_station_py.split(','):
                words = words + word
            toStationAddress.send_keys(words)
        time.sleep(1)
        isFind = self.isHavePage(wait, isFind, self.to_station)
        if isFind == 0:
            print('目的地输入错误')
            return False
        
        # 时间
        toStationAddress = self.driver.find_element(By.ID, 'train_date')
        toStationAddress.clear()
        toStationAddress.send_keys(self.start_time)
        
        # 2.等待出发地是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'fromStationText'), self.start)
        )
        # 3.等待目的地是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'toStationText'), self.to_station)
        )
        # 4.等待出发日期是否输入正确
        WebDriverWait(self.driver, 1000).until(
            
            EC.text_to_be_present_in_element_value((By.ID, 'train_date'), self.start_time)
        )
        # 5.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 1000).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )

    def cityFind(self, wait, isFind, address):
        formCities = wait.until(EC.presence_of_element_located((By.ID, 'form_cities')))
        formList = self.driver.find_elements(By.XPATH, '//*[@id="panel_cities"]/div')
        for city in formList:
            if city.find_element(By.CLASS_NAME, 'ralign').text == address:
                city.click()
                isFind = 1
                break
        return isFind
    def isHavePage(self, wait, isFind, address):
        over = 1
        while over:
            isFind = self.cityFind(wait, isFind, address)
            print(isFind)
            time.sleep(1)
            if isFind == 0:
                # 判断是否有分页
                page = self.driver.find_element(By.ID, "flip_cities")
                if page.is_displayed():
                    
                    pageChange    = page.find_elements(By.CLASS_NAME, 'pagetxt')
                    curFooterLink = page.find_element(By.CLASS_NAME, 'cur')
                    number = 0
                    for change in pageChange:
                        if number == 0:
                            if curFooterLink and curFooterLink.text == '1':
                                print(curFooterLink.text, 000)
                                change.click()
                                break
                            if len(pageChange) == 1:
                                over = 0
                            number = number + 1
                            continue
                        else:
                            change.click()
                            break
                else:
                    break
            else:
                break
        return isFind
    def hotAddressFind(self, wait):
        wait.until(EC.presence_of_element_located((By.ID, 'panel_cities2')))
        # 目的地热门地址
        hot = self.driver.find_element(By.XPATH, '//*[@id="panel_cities2"]/div[1]/div[1]')
        hot.click()
        wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="ul_list1"]/li')))

        startAddressList = self.driver.find_elements(By.XPATH, '//*[@id="ul_list1"]/li')
        return startAddressList
    # 点击查询按钮，进行车次和余票判断。
    # 用于while循环，持续检测余票信息。
    def _click_search(self):
        wait = WebDriverWait(self.driver, 100)
        element = wait.until(EC.presence_of_element_located((By.ID, 'query_ticket')))

        # 1.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 100).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )
        # 点击查询按钮
        queryBtn = self.driver.find_element(By.ID, 'query_ticket')
        queryBtn.click()

        # 等待查询页面有数据显示    

        # element1 = (By.XPATH, '//*[@id="queryLeftTable"]/tr')  
        # time.sleep(1)
        # element2 = self.driver.find_element(By.XPATH, '//*[@id="no_filter_ticket_6"]')  
        # print(element2.is_displayed())
        # if element2.is_displayed():
        #     return False
        trDom  = self.driver.find_elements(By.XPATH, '//*[@id="queryLeftTable"]/tr')
        # element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
        if not trDom:
            return False
        # element = wait.until(  
        #     lambda driver: self.driver.find_element(*element1).is_displayed() or self.driver.find_element(*element2).is_displayed()  
        # )  
        # //*[@id="no_filter_ticket_6"]/p
        tr_list = self.driver.find_elements(By.XPATH, '//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
        # print(element2)
        for tr in tr_list:
            if tr.is_displayed():
                train_number = tr.find_element(By.CLASS_NAME, 'number').text
            else:
                continue
            if train_number in self.train_num.split(','):
                xpath = ".//td" + str(self.seat)
                ticket = tr.find_element(By.XPATH, xpath).text
                if ticket == '有' or ticket.isdigit():
                    self.sure_train = train_number
                    print('符合条件的车次有：' + train_number + '，硬座车票状态：' + ticket)
                    presentBtn = tr.find_element(By.CLASS_NAME, 'btn72')
                    print('btn72')
                    presentBtn.click()
                    # 成功检测到了符合条件的车票
                    return True
        # 未检测到符合条件的车票
        return False

    # 提交订单
    def _present(self):
        print('到达订单')
        # 等待到达订单页面
        WebDriverWait(self.driver, 1000).until(
            EC.url_to_be(self.confirmPassenger_url)
        )
        print('------进入订单页面------')
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, '//ul[@id="normal_passenger_id"]/li'))
        )
        Spectator = self.driver.find_elements(By.XPATH, '//ul[@id="normal_passenger_id"]/li')
        for one in Spectator:
            person_name = one.find_element(By.XPATH, './label').text
            name = re.sub(r'\(.*?\)', '', person_name)
            if name in self.peoples.split(','):
                personBtn = one.find_element(By.XPATH, './label')
                personBtn.click()
                if self.isElementExits('//a[@id="qd_closeDefaultWarningWindowDialog_id"]'):
                    self.driver.find_element(
                        By.XPATH,
                        '//div[@id="content_defaultwarningAlert_id"]//a[@class="btn92s"]').click()

        print('乘客已选中...')

        # 选则座位等级，默认普通火车硬座
        selectTag = Select(self.driver.find_element(By.ID, 'seatType_1'))
        # value=1是硬座，O是高铁二等座。其他的去查网站源码。
        selectTag.select_by_value('O')

        # 提交订单
        WebDriverWait(self.driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//a[@id="submitOrder_id"]'))
        )

        submitBtn = self.driver.find_element(By.XPATH, '//a[@id="submitOrder_id"]')
        submitBtn.click()

        # 确定订单
        WebDriverWait(self.driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="qr_submit_id"]'))
        )
        sure_submitBtn = self.driver.find_element(By.XPATH, '//*[@id="qr_submit_id"]')
        WebDriverWait(self.driver, 20).until(
            EC.element_to_be_clickable((By.XPATH, '//*[@id="qr_submit_id"]'))
        )
        time.sleep(2)
        sure_submitBtn.click()
        print('订单已提交！')
        self.emailClass.sendEmailOk(to_addr=self.my_mail, content='你已成功抢到了%s车次车票，请在30分钟内前往付款！' % self.sure_train)

    # 检查元素是存在：
    def isElementExits(self, xpath):
        s = self.driver.find_elements(By.XPATH, xpath)
        if len(s) == 0:
            return False
        else:
            return True

    # 循环查询车票
    def _put_order(self):
        while True:
            flag = self._click_search()
            if flag:
                return True
            self.search_time += 1
            print('第{}次搜索！'.format(self.search_time))
            if self.search_time > self.times:
                self.life  += 1
                print('已完成第{}轮搜索'.format(self.life))
                print('已搜索{}次车票信息！暂时没有符合你条件的车票！'.format(self.times))
                if self.life % 10 == 0:
                    self.emailClass.sendSearchMessage(to_addr=self.my_mail, content='已完成第' + str(self.life) + '轮搜索，暂时没有符合你条件的车票！')
                if self.isExit == 1:
                    if self.life >= self.maxTimes:
                        print('非常抱歉，暂时没有符合你条件的车票！')
                        return False
                if self.searchSleep():
                    self.search_time = 0
                    continue

    def searchSleep(self):
        print('当前休息中......')
        # time.sleep(self.sleepTime * 60)
        return True
    def run(self):
        self._login()
        print('登录成功！')
        self._search_infor()
        # 如果有票，就执行订票函数。
        if self._put_order():
            self._present()


if __name__ == '__main__':
    spider = Qiangpiao()
    spider.run()
